#include "hough_plugin.h"

#include "ui_plugin.h"

#define         HOUGH_LINE_PAGE       0
#define         HOUGH_CIRCLE_PAGE     1

Hough_Plugin::Hough_Plugin()
{
    // Insert initialization codes here ...
}

Hough_Plugin::~Hough_Plugin()
{
    // Insert cleanup codes here ...
}

QString Hough_Plugin::title()
{
    return this->metaObject()->className();
}

QString Hough_Plugin::version()
{
    return "1.0.0";
}

QString Hough_Plugin::description()
{
    return "A <b>Template</b> plugin";
}

QString Hough_Plugin::help()
{
    return "This is a <b>Template</b> plugin. Clone and use it to create new plugins.";
}

void Hough_Plugin::setupUi(QWidget *parent)
{
    ui = new Ui::PluginGui;
    ui->setupUi(parent);

    ui->mainTab->setCurrentIndex(0);
    connect(ui->mainTab, SIGNAL(currentChanged(int)), this, SLOT(on_mainTab_currentChanged(int)));

    connect(ui->HoughLinesRadio, SIGNAL(toggled(bool)), this, SLOT(on_HoughLinesRadio_toggled(bool)));
    connect(ui->HoughLinesPRadio, SIGNAL(toggled(bool)), this, SLOT(on_HoughLinesPRadio_toggled(bool)));

    connect(ui->lineRhoSpin, SIGNAL(valueChanged(double)), this, SLOT(on_lineRhoSpin_valueChanged(double)));
    connect(ui->lineThetaSpin, SIGNAL(valueChanged(double)), this, SLOT(on_lineThetaSpin_valueChanged(double)));
    connect(ui->lineThreSpin, SIGNAL(valueChanged(int)), this, SLOT(on_lineThreSpin_valueChanged(int)));
    connect(ui->lineMInlineLenSpin, SIGNAL(valueChanged(double)), this, SLOT(on_lineMInlineLenSpin_valueChanged(double)));
    connect(ui->lineMaxLinegapSpin, SIGNAL(valueChanged(double)), this, SLOT(on_lineMaxLinegapSpin_valueChanged(double)));
    connect(ui->cannyTh1Spin, SIGNAL(valueChanged(int)), this, SLOT(on_cannyTh1Spin_valueChanged(int)));
    connect(ui->cannyTh2Spin, SIGNAL(valueChanged(int)), this, SLOT(on_cannyTh2Spin_valueChanged(int)));

    connect(ui->circleDpSpin, SIGNAL(valueChanged(double)), this, SLOT(on_circleDpSpin_valueChanged(double)));
    connect(ui->circleMindstSpin, SIGNAL(valueChanged(double)), this, SLOT(on_circleMindstSpin_valueChanged(double)));
    connect(ui->circleP1Spin, SIGNAL(valueChanged(double)), this, SLOT(on_circleP1Spin_valueChanged(double)));
    connect(ui->circleP2Spin, SIGNAL(valueChanged(double)), this, SLOT(on_circleP2Spin_valueChanged(double)));
    connect(ui->circleMinRSpin, SIGNAL(valueChanged(int)), this, SLOT(on_circleMinRSpin_valueChanged(int)));
    connect(ui->circleMaxRSpin, SIGNAL(valueChanged(int)), this, SLOT(on_circleMaxRSpin_valueChanged(int)));

    connect(ui->circleUrl,SIGNAL(linkActivated(QString)),this,SLOT(openURL(QString)));
    connect(ui->lineUrl,SIGNAL(linkActivated(QString)),this,SLOT(openURL(QString)));


}

void Hough_Plugin::processImage(const cv::Mat &inputImage, cv::Mat &outputImage)
{
    using namespace cv;
    using namespace std;
    Mat gray;
    cvtColor(inputImage,gray,COLOR_BGR2GRAY);

    switch (ui->mainTab->currentIndex()) {
        case HOUGH_LINE_PAGE:{
            Canny(gray,gray,ui->cannyTh1Spin->value(),ui->cannyTh2Spin->value());
            if(ui->HoughLinesRadio->isChecked()){
                            vector<Vec2f> lines;
                            HoughLines(gray,lines,ui->lineRhoSpin->value(),
                                       (CV_PI/ui->lineThetaSpin->value()),
                                       ui->lineThreSpin->value());

                            cvtColor(gray,outputImage,COLOR_GRAY2BGR);
                            for(size_t i=0;i<lines.size();i++)
                            {
                                float r=lines[i][0];
                                float theta=lines[i][1];
                                Point pt1,pt2;
                                double a=cos(theta),b=sin(theta);
                                double x0=a*r,y0=b*r;
                                pt1.x=cvRound(x0+1000*(-b));
                                pt1.y=cvRound(y0+1000*a);
                                pt2.x=cvRound(x0-1000*(-b));
                                pt2.y=cvRound(y0-1000*a);
                                line(outputImage,pt1,pt2,Scalar(0,255,0),1,LINE_AA);
                            }
            }
            if(ui->HoughLinesPRadio->isChecked()){
                vector<Vec4f> plines;
                HoughLinesP(gray,plines,ui->lineRhoSpin->value(),
                            CV_PI/ui->lineThetaSpin->value(),
                            ui->lineThreSpin->value(),
                            ui->lineMInlineLenSpin->value(),
                            ui->lineMaxLinegapSpin->value());

                cvtColor(gray,outputImage,COLOR_GRAY2BGR);
                for(size_t i=0;i<plines.size();i++)
                {
                    Vec4i l = plines[i];
                    line(outputImage,Point(l[0],l[1]),Point(l[2],l[3]),Scalar(0,255,0),1,LINE_AA);
                }

            }
        }
            break;

        case HOUGH_CIRCLE_PAGE:{
            medianBlur(gray,gray,3);
            vector<Vec3f> hcircle;

            HoughCircles(gray,hcircle,HOUGH_GRADIENT,
                         ui->circleDpSpin->value(),
                         ui->circleMindstSpin->value(),
                         ui->circleP1Spin->value(),
                         ui->circleP2Spin->value(),
                         ui->circleMinRSpin->value(),
                         ui->circleMaxRSpin->value());

            cvtColor(gray,outputImage,COLOR_GRAY2BGR);
            for(size_t i=0;i<hcircle.size();i++)
            {
                Vec3f cc=hcircle[i];
                //圆心
                circle(outputImage,Point(cc[0],cc[1]),2,Scalar(123,67,89),2,LINE_AA);
                //半径
                circle(outputImage,Point(cc[0],cc[1]),cc[2],Scalar(0,0,255),2,LINE_AA);
            }

        }
            break;

        default:
            break;
    }
}

void Hough_Plugin::on_mainTab_currentChanged(int index)
{
    Q_UNUSED(index);
    emit updateNeeded();
}

void Hough_Plugin::on_HoughLinesRadio_toggled(bool checked)
{
    Q_UNUSED(checked);
    init(false);
    ui->lineText->setText("C++ API:<br>"
                          "void <b>HoughLines</b>( <br>"
                          "InputArray  image, <br>"
                          "OutputArray lines,<br>"
                          "double rho,<br>"
                          "double theta,<br>"
                          "int    threshold,<br>"
                          "double srn = 0,<br>"
                          "double stn = 0,<br>"
                          "double min_theta = 0,<br>"
                          "double max_theta = CV_PI <br>"
                          ")"
                          );
    emit updateNeeded();
}

void Hough_Plugin::on_HoughLinesPRadio_toggled(bool checked)
{
    Q_UNUSED(checked);
    init(true);
    ui->lineText->setText("C++ API:<br>"
                          "void <b>HoughLinesP</b>( <br>"
                          "InputArray  image, <br>"
                          "OutputArray lines,<br>"
                          "double rho,<br>"
                          "double theta,<br>"
                          "int    threshold,<br>"
                          "double minLineLength = 0,<br>"
                          "double maxLineGap = 0,<br>"
                          ")"
                          );
    emit updateNeeded();
}

void Hough_Plugin::on_lineRhoSpin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_lineThetaSpin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_lineThreSpin_valueChanged(int arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_lineMInlineLenSpin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_lineMaxLinegapSpin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_circleDpSpin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_circleMindstSpin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_circleP1Spin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_circleP2Spin_valueChanged(double arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_circleMinRSpin_valueChanged(int arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_circleMaxRSpin_valueChanged(int arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_cannyTh1Spin_valueChanged(int arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::on_cannyTh2Spin_valueChanged(int arg1)
{
    Q_UNUSED(arg1);
    emit updateNeeded();
}

void Hough_Plugin::init(bool a)
{

    ui->cannyTh1Spin->setEnabled(true);
    ui->cannyTh1Spin->setValue(0);
    ui->cannyTh2Spin->setEnabled(true);
    ui->cannyTh2Spin->setValue(0);
    ui->lineRhoSpin->setEnabled(true);
    ui->lineRhoSpin->setValue(1.00);
    ui->lineThetaSpin->setEnabled(true);
    ui->lineThetaSpin->setValue(180);
    ui->lineThreSpin->setEnabled(true);
    ui->lineThreSpin->setValue(0);
    ui->lineMInlineLenSpin->setEnabled(a);
    ui->lineMInlineLenSpin->setValue(0.00);
    ui->lineMaxLinegapSpin->setEnabled(a);
    ui->lineMaxLinegapSpin->setValue(0.00);

}

void Hough_Plugin::openURL(QString url)
{
    QDesktopServices::openUrl(url);
}
